home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / progjour / 1991 / 06 / hercline.asm < prev    next >
Assembly Source File  |  1991-03-06  |  13KB  |  458 lines

  1. ; hercline.asm: line-drawing routine for the Hercules monochrome
  2. ;   graphics card.
  3. ; Copyright (C) 1990 by Nicholas Wilt.    All rights reserved.
  4.  
  5. .MODEL    COMPACT
  6.  
  7.     PAGE    ,132
  8.  
  9. .CODE
  10.  
  11.     ASSUME    cs:_TEXT,ds:_TEXT
  12.  
  13.     PUBLIC    _hercline
  14.  
  15. BytesPerRow    EQU    90    ; Change to 80 for 640x400 mode
  16. BytesPerBank    EQU    7830    ; Change to 8000 for 640x400 mode
  17.                 ; BytesPerBank is (YRes/4)*BytesPerRow.
  18.  
  19. ; The IncY and DecY macros update the offset-mask pair in DI and AH to
  20. ; point to the above or below pixel.  They do not depend on whether
  21. ; the routine is drawing or erasing.
  22. IncY    MACRO
  23.     LOCAL    ExitIncY
  24.     add    di,bp        ;; 8192 in BP
  25.     jno    ExitIncY    ;; Leave if done
  26.                 ;; Undo and compensate
  27.     sub    di,24576+BytesPerBank-BytesPerRow+8192
  28.     jge    ExitIncY    ;; Leave if done
  29.     add    di,BytesPerBank ;; Undo and compensate
  30. ExitIncY:
  31.     ENDM
  32.  
  33. DecY    MACRO
  34.     LOCAL    ExitDecY
  35.     sub    di,bp              ;; 8192 in BP
  36.     jns    ExitDecY          ;; Leave if done
  37.     sub    di,BytesPerRow-8192-24576 ;; Undo and compensate
  38.     jge    ExitDecY          ;; Leave if done
  39.     add    di,BytesPerBank       ;; Undo and compensate
  40. ExitDecY:
  41.     ENDM
  42.  
  43. ; ******************************************************************
  44. ; void hercline(int x1, int y1, int x2, int y2, int color);
  45. ; C-callable in tiny, small, compact memory models.
  46. ; To use medium, large, or huge, just add 2 to the indices when
  47. ; loading the parameters.
  48. ; Color is nonzero to draw the line, 0 to erase the line (set to 0).
  49. ; ******************************************************************
  50. _hercline    PROC
  51.     push    bp        ; Enter
  52.     mov    bp,sp        ; Set up stack frame
  53.     push    ds        ; Save regs
  54.     push    di        ;
  55.     push    si        ;
  56.  
  57. ; Add two to each of the indices below to use a large code model.
  58.     mov    ax,[bp+4]    ; Load x1
  59.     mov    bx,[bp+6]    ; Load y1
  60.     mov    cx,[bp+8]    ; Load x2
  61.     mov    dx,[bp+10]    ; Load y2
  62.     mov    bp,[bp+12]    ; Load color into BP.  Dangerous.
  63.  
  64.     cld            ; String ops go forward
  65.     push    cs        ; Copy CS to DS for table lookup
  66.     pop    ds        ;
  67.  
  68.     sub    dx,bx        ; DX <- diffy
  69.     sub    cx,ax        ; CX <- diffx
  70.     jge    CheckForNull    ; Jump if x2 >= x1
  71.     add    ax,cx        ; Make ax contain x2
  72.     add    bx,dx        ; Make bx contain y2
  73.     neg    dx        ; Negate diffx and diffy
  74.     neg    cx        ;
  75. CheckForNull:            ; Make sure the line's start and end
  76.                 ; points are different
  77.     jnz    DrawLine    ; If diffx nonzero, draw the line
  78.     or    dx,dx        ; Check diffy against 0
  79.     jnz    DrawLine    ; If not zero, draw the line
  80.     jmp    LeaveLine    ; Do not try to draw line if
  81.                 ; x1==x2 && y1==y2
  82. DrawLine:
  83.     mov    di,ax        ; Load X into DI
  84.     shr    di,1        ; Divide by 8 for initial offset
  85.     shr    di,1        ;
  86.     shr    di,1        ;
  87.  
  88.     push    cx        ; Save DIFFX and DIFFY on stack
  89.     push    dx        ;
  90.     xchg    ax,cx        ; CX <- X; AX <- DIFFX
  91.     mov    ax,bx        ; AX <- Y
  92.  
  93.     and    bx,3        ; Add bank into offset
  94.     shl    bx,1        ;
  95.     add    di,Banks[BX]    ; Lookup table located after routine
  96.  
  97.     shr    ax,1        ; Divide Y by 4
  98.     shr    ax,1        ;
  99.     mov    dx,BytesPerRow    ; Load factor to multiply by
  100.     mul    dx        ; Perform multiply
  101.     add    di,ax        ; Add to offset
  102.  
  103.     and    cl,7        ; x &= 7
  104.     mov    ah,80h        ; AH <- Initial mask
  105.     shr    ah,cl        ;
  106.  
  107.     mov    cx,0B000H    ; Point DS and ES at video memory
  108.     mov    ds,cx        ;
  109.     mov    es,cx        ;
  110.  
  111.     mov    al,[di]     ; Pick up initial value
  112.     pop    dx        ; Restore DIFFX and DIFFY
  113.     pop    bx        ;
  114.     or    dx,dx        ; If DIFFY 0, draw span
  115.     jnz    CheckDrawing
  116.     call    hercspan    ; Call span routine
  117.     jmp    LeaveLine    ; Leave
  118. CheckDrawing:
  119.     or    bp,bp        ; Are we drawing?
  120.     jnz    CheckDIFFY    ; Yes, don't take one's comp of mask
  121.     not    ah        ; AH <- ~AH
  122. CheckDIFFY:
  123.     or    dx,dx        ; Compare DIFFY to 0
  124.     jl    DIFFYNegative    ; Jump if less than
  125.     jmp    DIFFYPositive
  126. DIFFYNegative:
  127.     mov    cx,dx        ; Copy DIFFY to CX for compare
  128.     neg    cx        ; Negate for compare
  129.     cmp    cx,bx        ; Compare to DIFFX
  130.     jle    LineXYM     ; Jump if -diffy <= diffx
  131. LineYMX:            ; Decrement Y before incrementing X
  132.                 ; (count is already in cx)
  133.     mov    si,dx        ; Initialize error
  134.     sar    si,1        ;
  135.     or    bp,bp        ; Are we drawing?
  136.     mov    bp,8192     ; Set up for changes in Y
  137.     jne    DrawYMX     ; Jump if yes
  138.  
  139. ; *************************************
  140. ; Loop: Erase, decrement Y, and increment X if appropriate.
  141. ; *************************************
  142. EraseYMX:
  143.     and    byte ptr [di],ah ; Erase
  144.     sub    di,bp        ; Decrement Y
  145.     js    FixupEraseYMX    ; Jump if we need to fixup
  146. ContinueEraseYMX:
  147.     add    si,bx        ; Add DIFFX to error
  148.     jns    ELoopYMX    ; Jump if positive
  149.     loop    EraseYMX    ; Loop until done
  150.     jmp    short DoneEYMX    ; Leave if done
  151. FixupEraseYMX:
  152.     sub    di,BytesPerRow-8192-24576 ; Undo and compensate
  153.     jge    ContinueEraseYMX  ; Leave if done
  154.     add    di,BytesPerBank   ; Undo and compensate
  155.     jmp    short ContinueEraseYMX
  156. ELoopYMX:
  157.     ror    ah,1        ; Increment X
  158.     sbb    di,-1        ;
  159.     add    si,dx        ; Add DIFFY to error
  160.     loop    EraseYMX    ; Loop until done
  161. DoneEYMX:
  162.     and    byte ptr [di],ah ; Last plot
  163.     jmp    LeaveLine    ; Jump to exit code
  164.  
  165. ; *************************************
  166. ; Loop: Draw, decrement Y, and increment X if appropriate.
  167. ; *************************************
  168. DrawYMX:
  169.     or     byte ptr [di],ah ; Plot
  170.     sub    di,bp        ; Decrement Y
  171.     js    FixupDrawYMX    ; Jump if fixup needed
  172. ContinueDrawYMX:
  173.     add    si,bx        ; Add DIFFX to err
  174.     jns    DLoopYMX    ; Jump if positive
  175.     loop    DrawYMX     ; Loop until done
  176.     jmp    short DoneDYMX    ; Jump if done
  177. FixupDrawYMX:
  178.     sub    di,BytesPerRow-8192-24576 ; Undo and compensate
  179.     jge    ContinueDrawYMX       ; Leave if done
  180.     add    di,BytesPerBank       ; Undo and compensate
  181.     jmp    short ContinueDrawYMX
  182. DLoopYMX:
  183.     ror    ah,1        ; Increment X
  184.     adc    di,0        ;
  185.     add    si,dx        ; Add DIFFY
  186.     loop    DrawYMX     ; Loop until done
  187. DoneDYMX:
  188.     or    byte ptr [di],ah ; Last plot
  189.     jmp    LeaveLine    ; Jump to exit code
  190.  
  191. LineXYM:
  192.     mov    cx,bx        ; Get count
  193.     mov    si,bx        ; Initialize error
  194.     neg    si        ;
  195.     sar    si,1        ;
  196.     or    bp,bp        ; Are we drawing?
  197.     mov    bp,8192     ; Set up for changes in Y
  198.     jne    DrawXYM     ; Jump if drawing
  199.  
  200. ; *************************************
  201. ; Loop: Erase, increment X, and decrement Y if appropriate.
  202. ; *************************************
  203. EraseXYM:
  204.     and    al,ah        ; Erase
  205.     ror    ah,1        ; Rotate mask right
  206.     jnc    GetNextEraseXYM ; Jump if we need another byte
  207. ContinueEraseXYM:
  208.     sub    si,dx        ; Subtract DIFFY from err
  209.     jns    ELoopXYM    ; Jump if positive
  210.     loop    EraseXYM    ; Loop until done
  211.     jmp    short DoneEXYM    ; Jump if done
  212. GetNextEraseXYM:
  213.     stosb            ; Store and increment DI
  214.     mov    al,[di]     ; Get next byte
  215.     jmp    short ContinueEraseXYM
  216. ELoopXYM:
  217.     mov    [di],al     ; Save to video memory
  218.     DecY            ; Decrement Y
  219.     mov    al,[di]     ; Load from video memory
  220.     sub    si,bx        ; Subtract DIFFX from err
  221.     loop    EraseXYM    ; Loop until done
  222. DoneEXYM:
  223.     and    al,ah        ; Last plot
  224.     jmp    WriteLastByte    ; Jump to exit code
  225.  
  226. ; *************************************
  227. ; Loop: Draw, increment X, and decrement Y if appropriate.
  228. ; *************************************
  229. DrawXYM:
  230.     or    al,ah        ; Plot
  231.     ror    ah,1        ; Rotate mask right
  232.     jc    GetNextDrawXYM    ; Jump if we need another byte
  233. DrawContinueXYM:
  234.     sub    si,dx        ; Subtract DIFFY from err
  235.     jns    DLoopXYM    ; Jump if positive
  236.     loop    DrawXYM     ; Loop until done
  237.     jmp    short DoneDXYM    ; Jump if done
  238. GetNextDrawXYM:
  239.     stosb            ; Store and increment DI
  240.     mov    al,[di]     ;
  241.     jmp    short DrawContinueXYM
  242. DLoopXYM:
  243.     mov    [di],al     ; Save to video memory
  244.     DecY            ; Decrement Y
  245.     mov    al,[di]     ; Load from video memory
  246.     sub    si,bx        ; Subtract DIFFX
  247.     loop    DrawXYM     ; Loop until done
  248. DoneDXYM:
  249.     or    al,ah        ; Plot last
  250.     jmp    WriteLastByte    ; Jump to exit code
  251.  
  252. DIFFYPositive:
  253.     cmp    dx,bx        ; Compare DIFFY to DIFFX
  254.     jle    LineXYP     ; Jump if less than or equal to
  255. LineYPX:
  256.     mov    cx,dx        ; Load count
  257.     mov    si,dx        ; Initialize error
  258.     neg    si        ;
  259.     sar    si,1        ;
  260.     or    bp,bp        ; Are we drawing?
  261.     mov    bp,8192     ; Set up for changes in Y
  262.     jne    DrawYPX     ; Jump if yes
  263.  
  264. ; *************************************
  265. ; Loop: Erase, increment Y, and increment X if appropriate.
  266. ; *************************************
  267. EraseYPX:
  268.     and    byte ptr [di],ah ; Erase
  269.     add    di,bp        ; Increment Y
  270.     jo    FixupEraseYPX    ; Jump if fixup needed
  271. ContinueEraseYPX:
  272.     add    si,bx        ; Add DIFFX to err
  273.     jns    ELoopYPX    ; Jump if positive
  274.     loop    EraseYPX    ; Loop until done
  275.     jmp    short DoneEYPX    ; Jump if done
  276. FixupEraseYPX:
  277.     sub    di,24576+BytesPerBank-BytesPerRow+8192
  278.     jge    ContinueEraseYPX ; Leave if done
  279.     add    di,BytesPerBank ; Undo and compensate
  280.     jmp    short ContinueEraseYPX
  281. ELoopYPX:
  282.     ror    ah,1        ; Increment X
  283.     sbb    di,-1        ;
  284.     sub    si,dx        ; Subtract DIFFY from err
  285.     loop    EraseYPX    ; Loop until done
  286. DoneEYPX:
  287.     and    byte ptr [di],ah ; Erase last
  288.     jmp    LeaveLine    ; Jump to exit code
  289.  
  290. ; *************************************
  291. ; Loop: Draw, increment Y, and increment X if appropriate.
  292. ; *************************************
  293. DrawYPX:
  294.     or    byte ptr [di],ah ; Plot
  295.     add    di,bp        ; Increment Y
  296.     jo    FixupDrawYPX    ; Jump if fixup needed
  297. ContinueDrawYPX:
  298.     add    si,bx        ; Add DIFFX to err
  299.     jns    DLoopYPX    ; Jump if positive
  300.     loop    DrawYPX     ; Loop until done
  301.     jmp    short DoneDYPX    ; Jump if done
  302. FixupDrawYPX:
  303.     sub    di,24576+BytesPerBank-BytesPerRow+8192
  304.     jge    ContinueDrawYPX ; Leave if done
  305.     add    di,BytesPerBank ; Undo and compensate
  306.     jmp    short ContinueDrawYPX
  307. DLoopYPX:
  308.     ror    ah,1        ; Increment X
  309.     adc    di,0        ;
  310.     sub    si,dx        ; Subtract DIFFY from err
  311.     loop    DrawYPX     ; Loop until done
  312. DoneDYPX:
  313.     or    byte ptr [di],ah ; Plot last
  314.     jmp    short LeaveLine ; Jump to exit code
  315.  
  316. LineXYP:
  317.     mov    cx,bx        ; Load count
  318.     mov    si,cx        ; Initialize error
  319.     neg    si        ;
  320.     sar    si,1        ;
  321.     or    bp,bp        ; Are we drawing?
  322.     mov    bp,8192     ; Set up for changes in Y
  323.     jne    DrawXYP     ; Jump if yes
  324.  
  325. ; *************************************
  326. ; Loop: Erase, increment X, and increment Y if appropriate.
  327. ; *************************************
  328. EraseXYP:
  329.     and    al,ah        ; Erase
  330.     ror    ah,1        ; Rotate mask right
  331.     jnc    GetNextEraseXYP ; Jump if we need another byte
  332. ContinueEraseXYP:
  333.     add    si,dx        ; Add DIFFY to err
  334.     jns    ELoopXYP    ; Jump if positive
  335.     loop    EraseXYP    ; Loop until done
  336.     jmp    short DoneEXYP    ; Jump to end
  337. GetNextEraseXYP:
  338.     stosb            ; Store and increment DI
  339.     mov    al,[di]     ; Get next byte
  340.     jmp    short ContinueEraseXYP
  341. ELoopXYP:
  342.     mov    [di],al     ; Save to video memory
  343.     IncY            ; Increment Y
  344.     mov    al,[di]     ; Load from video memory
  345.     sub    si,bx        ; Add DIFFX to err
  346.     loop    EraseXYP    ; Loop until done
  347. DoneEXYP:
  348.     and    al,ah        ; Erase last
  349.     jmp    short WriteLastByte
  350.  
  351. ; *************************************
  352. ; Loop: Draw, increment X, and increment Y if appropriate.
  353. ; *************************************
  354. DrawXYP:
  355.     or    al,ah        ; Plot
  356.     ror    ah,1        ; Rotate mask right
  357.     jc    GetNextDrawXYP    ; Jump if we need another byte
  358. DrawContinueXYP:
  359.     add    si,dx        ; Add DIFFY to err
  360.     jns    DLoopXYP    ; Jump if positive
  361.     loop    DrawXYP     ; Loop until done
  362.     jmp    short DoneDXYP    ; Jump if done
  363. GetNextDrawXYP:
  364.     stosb            ; Store byte and increment
  365.     mov    al,[di]     ; Get next byte
  366.     jmp    short DrawContinueXYP
  367. DLoopXYP:
  368.     mov    [di],al     ; Save to video memory
  369.     IncY            ; Increment Y
  370.     mov    al,[di]     ; Load from video memory
  371.     sub    si,bx        ; Subtract DIFFX from err
  372.     loop    DrawXYP     ; Loop until done
  373. DoneDXYP:
  374.     or    al,ah        ; Plot last
  375.  
  376. WriteLastByte:            ; Write the last byte before exiting
  377.     mov    [di],al     ; Save final byte
  378. LeaveLine:
  379.     pop    si        ; Restore registers
  380.     pop    di        ;
  381.     pop    ds        ;
  382.     pop    bp        ; Restore stack frame
  383.     ret            ; Exit routine
  384.  
  385. Banks    DW    0,8192,16384,24576
  386.  
  387. _hercline    ENDP
  388.  
  389. ; hercspan called from _hercline if line is horizontal.
  390. ; Input register states as follows:
  391. ;    DS,ES    0B000H
  392. ;    BX    DIFFX
  393. ;    DX    0 (DIFFY)
  394. ;    BP    0 if erasing, nonzero if drawing
  395. ;    AL    initial value
  396. ;    AH    initial mask
  397. hercspan    PROC
  398.     mov    cx,bx        ; Get count into CX
  399.     or    bp,bp        ; Are we drawing?
  400.     jnz    DrawFirstLoop    ; Yes
  401.     not    ah        ; AH <- ~AH
  402. EraseFirstLoop:
  403.     and    al,ah        ; Write pixel
  404.     dec    cx        ; Decrement CX
  405.     ror    ah,1        ; Rotate mask right
  406.     jnc    DoneEraseFirstLoop
  407.     jcxz    DoneEraseFirstLoop
  408.     jmp    short EraseFirstLoop
  409. DoneEraseFirstLoop:
  410.     stosb            ; Store byte
  411.     mov    dx,cx        ; Copy count remaining
  412.     shr    cx,1        ; Divide by 8
  413.     shr    cx,1        ;
  414.     shr    cx,1        ;
  415.     sub    dx,cx        ; Find remainder
  416.     xor    al,al        ; Write 0's
  417.     rep    stosb        ;
  418.     mov    cx,dx        ; Copy remainder to CX
  419.     jcxz    LeaveSpan    ; Leave if done
  420.     mov    al,[di]     ;
  421.     mov    ah,7fh        ; Set mask
  422. EraseSecondLoop:
  423.     and    al,ah        ; Write pixel
  424.     ror    ah,1        ; Rotate mask right
  425.     loop    EraseSecondLoop  ;
  426.     stosb            ; Store byte
  427.     jmp    short LeaveSpan ; Leave
  428. DrawFirstLoop:
  429.     or    al,ah        ; Write pixel
  430.     dec    cx        ; Decrement CX
  431.     ror    ah,1        ; Rotate mask right
  432.     jc    DoneDrawFirstLoop
  433.     jcxz    DoneDrawFirstLoop
  434.     jmp    short DrawFirstLoop
  435. DoneDrawFirstLoop:
  436.     stosb            ; Store byte
  437.     mov    dx,cx        ; Copy count remaining
  438.     shr    cx,1        ; Divide by 8
  439.     shr    cx,1        ;
  440.     shr    cx,1        ;
  441.     sub    dx,cx        ; Find remainder
  442.     mov    al,0FFh     ; Write FF's
  443.     rep    stosb        ;
  444.     mov    cx,dx        ; Copy remainder to CX
  445.     jcxz    LeaveSpan    ; Leave if done
  446.     mov    al,[di]     ;
  447.     mov    ah,80h        ; Set mask
  448. DrawSecondLoop:
  449.     or    al,ah        ; Write pixel
  450.     ror    ah,1        ; Rotate mask right
  451.     loop    DrawSecondLoop    ;
  452.     stosb            ; Store byte
  453. LeaveSpan:
  454.     ret
  455. hercspan    ENDP
  456.  
  457.     END
  458.